using System;
using System.Collections.Generic;
using CLELCore.Assembly.Descriptors;
using CLELCore.Assembly.Descriptors.ClassDescriptors;

namespace CLELCore.Assembly.BlobStreams.BlobInfo
{
	public class MethodBlobInfo
	{
		private byte _calling_flags;
		private List<ParameterDescriptor> _params;
		private ReturnDescriptor _ret;

		public byte CallingFlags
		{
			get
			{
				return _calling_flags;
			}
		}

		public List<ParameterDescriptor> Parameters
		{
			get
			{
				return _params;
			}
		}

		public ReturnDescriptor ReturnType
		{
			get
			{
				return _ret;
			}
		}

		public MethodBlobInfo(byte [] blob,uint ordinal_number,CLELAssembly assembly)
		{
			//for(int k = 0;k < blob.Length;k++)
			//	Console.Write(blob[k]+" ");
			//Console.WriteLine("\n");
			if(blob == null)
				throw new ArgumentException("Blob cannot be null");
			int len = blob.Length;
			int start = 0;
			//parse blob length and ignore it
			Blob.DecompressBlobValue(blob,ref start);
			if(start < len)
			{
				//get method calling flags
				_calling_flags = blob[start];
				start++;
			}
			else
			{
				throw new CLELParserException("Error missing blob calling flags");
			}
			ClassDescriptor blob_type;
			uint p_count = 0;
			if(start < len)
			{
				//get number of parameters
				p_count = (uint)Blob.DecompressBlobValue(blob,ref start);
				//get return type
				blob_type = ClassDescriptor.ParseMethodReturnTypeFromBlob(assembly,blob,ref start);	
				_ret = new ReturnDescriptor(blob_type);
			}
			else
			{
				throw new CLELParserException("Error missing blob param count");
			}
			//P. 282
			//P. 277
			//10 = length
			//32 = HASTHIS
			//3 = param count
			//1 = Return type = void
			//21 = GENERICINST  18 = TYPE_CLASS  9 = TYPEREF row 2  1 = arg count   8 = I4
			//8 = I4
			//8 = I4
			//10,32,3,1,21,18,9,1,8,8,8
			_params = new List<ParameterDescriptor>();
			uint i;
			ParameterDescriptor parm;
			for(i = 0;i < p_count;i++)
			{
				if(start < len)
				{
					//read parameter
					blob_type = ClassDescriptor.ParseMethodParameterTypeFromBlob(assembly,blob,ref start);
					parm = new ParameterDescriptor(blob_type,ordinal_number);
					ordinal_number++;
					_params.Add(parm);
				}
				else
				{
					throw new CLELParserException("Error parsing method parameter: " + start);
				}
			}
		}
	}
}
